package nkr1pt.popkorn.download;

import java.io.File;
import java.io.InputStream;
import nkr1pt.popkorn.events.DownloadEvent;
import nkr1pt.popkorn.events.EventBus;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
import nkr1pt.popkorn.events.PopkornEvent.EventType;
import nkr1pt.popkorn.events.PopkornEventFactory;
import nkr1pt.popkorn.helper.FileUtils;
import org.apache.commons.lang.StringUtils;

/**
 *
 * @author Kristof Vanhaeren
 */
public class Downloader {

    private EventBus eventBus;
    private static final Logger logger = Logger.getLogger(Downloader.class.getName());
    private PopkornEventFactory eventFactory;

    public Downloader(EventBus eventBus, PopkornEventFactory eventFactory) {
        this.eventBus = eventBus;
        this.eventFactory = eventFactory;
    }

    public void download(DownloadCandidateItem item) {
        InputStream is = null;
        RandomAccessFile raf = null;
        try {
            HttpURLConnection urlConn = (HttpURLConnection)item.getUrl().openConnection();
            if (!StringUtils.isEmpty(item.getCookie())) {
                urlConn.setRequestProperty("Cookie", item.getCookie());
            }
            urlConn.setRequestProperty("Range", "bytes="+item.getDownloaded()+"-");

            int responseCode = urlConn.getResponseCode();
            if (responseCode / 100 != 2) {
                item.setState(DownloadCandidateState.FAILED);
                throw new RuntimeException("HTTP Reponse Code was " + responseCode);
            }

            File outputFile = FileUtils.createFile(item.getAbsolutePath());
            if (outputFile == null) {
                throw new IOException(item.getAbsolutePath() + " could not be created.");
            }

            raf = new RandomAccessFile(outputFile, "rw");
            raf.seek(item.getDownloaded());

            is = urlConn.getInputStream();

            eventBus.fireEvent(eventFactory.newEvent(EventType.DOWNLOAD_STARTED, item));

            int read;
            byte[] buffer = new byte[2048];
            while ((read = is.read(buffer)) != -1) {
                raf.write(buffer, 0, read);
            }

            urlConn.disconnect();
            eventBus.fireEvent(eventFactory.newEvent(EventType.DOWNLOAD_COMPLETED, item));
        } catch (Exception e) {
            DownloadEvent event = eventFactory.newEvent(EventType.DOWNLOAD_FAILED, item);
            event.setException(e);
            eventBus.fireEvent(event);
        } finally {
            try {
                if (is != null) is.close();
                if (raf != null) raf.close();
            } catch (IOException ex) {
                logger.log(Level.SEVERE, ex.getMessage());
            }
        }
    }

}